package org.breathe.datastruct.impl;

import org.breathe.datastruct.RedisBytes;
import org.breathe.datastruct.RedisData;
import org.breathe.internal.Dict;
import org.breathe.protocal.Resp;
import org.breathe.protocal.decode.BulkString;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

/**
 * 源码中如果全部使用的是数字那么就先用intSet，一旦有了Object，就使用RedisSet，我这里直接使用RedisSet
 * @author: breathe
 * @createTime: 2025-05-13
 */
public class RedisSet implements RedisData {
    private volatile long timeout = -1;
    private Dict<RedisBytes, Object> setCore;
    public RedisSet() {
        this.setCore =new Dict<>();
    }
    @Override
    public long timeout() {
        return timeout;
    }

    @Override
    public void setTimeout(long timeout) {
        this.timeout = timeout;
    }

    @Override
    public List<Resp> convertToResp() {
        List<Resp> result = new ArrayList<>();
        if (setCore.size() == 0) {
            return Collections.emptyList();
        }
        for (RedisBytes key : setCore.keySet()) {
            result.add(new BulkString(key));
        }
        return result;
    }

    public int add(List<RedisBytes> members) {
        int count = 0;
        for (RedisBytes member : members) {
            if (!setCore.containsKey(member)) {
                count ++;
                setCore.put(member, null);
            }
        }
        return count;
    }
    public int remove(RedisBytes member) {
        int count = 0;
        if (setCore.containsKey(member)) {
            count ++;
            setCore.remove(member);
        }
        return count;
    }
    public List<RedisBytes> pop(int count) {
        if (setCore.size() == 0) {
            return Collections.EMPTY_LIST;
        }
        count = Math.min(count, setCore.size());
        List<RedisBytes> poppedElements = new ArrayList<>(count);
        Random random = new Random();
        for (int i = 0; i < count; i ++) {
            RedisBytes member = (RedisBytes) setCore.keySet().toArray()[random.nextInt(setCore.size())];
            poppedElements.add(member);
            setCore.remove(member);
        }
        return poppedElements;
    }
    public int size() {
        return setCore.size();
    }

    public RedisBytes[] getAll() {
        RedisBytes[] result = new RedisBytes[setCore.size()];
        int i = 0;
        for(RedisBytes key : setCore.keySet()){
            result[i++] = key;
        }
        return result;
    }
}